/**
 * @file innervent.c
 * @brief 实现对事件信封功能
 * @author ken (kangjiening@openvalley.net)
 * @version 0.1
 * @date 2023-06-08
 *
 * @copyright Copyright (c) 2023  湖南开鸿智谷数字产业发展有限公司
 *
 * @par 修改日志:
 *     @date 2023-06-08
 *     @version 0.2
 *     @author xx
 *     @brief xx
 */
#include "config.h"
#include "innervent.h"

/**
 * @briefzheli you jihui yingg shiyong C banben de vetcor
 *
 * @param eventPoolSzie
 * @return UNTPTR
 */
struct InnerEventPool_S *InnerEventPoolCreate(int maxPoolSize)
{
    InnerEvent_S *innerEventHead = NULL;
    if (maxPoolSize <= 0)
        return NULL;
    innerEventHead = (struct InnerEvent_S *)Event_Malloc(sizeof(struct InnerEvent_S *) * (maxPoolSize + 1));
    if (innerEventHead == NULL)
        return NULL;
    memset(innerEventHead, 0, sizeof(UNTPTR) * (maxPoolSize + 1));
    struct InnerEventPool_S *innerEventPool = (struct InnerEventPool_S *)Event_Malloc(sizeof(struct InnerEventPool_S));
    if (innerEventPool == NULL)
    {
        Event_free(innerEventHead);
        innerEventHead == NULL;
        return NULL;
    }
    innerEventPool->mutex = MUTEX_InitValue();
    if (innerEventPool->mutex)
    {
        Event_free(innerEventHead);
        innerEventHead = NULL;
        Event_free(innerEventPool);
        innerEventPool = NULL;
        return NULL;
    }
    innerEventPool->maxPoolSize = maxPoolSize;
    innerEventPool->ptrPool = innerEventHead;

    return innerEventPool;
}
/**
 * @brief 查询池子可用的下标
 * @param [in] pool
 * @return int
 *
 * @details
 * @author ken (kangjiening@openvalley.net)
 * @date 2023-06-13
 */
static int InnerEventGetIndex(struct InnerEventPool_S *pool)
{
    int iCount = 0;
    if (pool == NULL)
        return -1;
    for (iCount = 0; i < pool->maxPoolSize; iCount++)
    {
        if (pool->ptrPool = NULL)
            return iCount;
    }
    return -1;
}
static int InnerEventGetIndexByBody(struct InnerEventPool_S *pool, struct InnerEvent_S *innerEvent)
{
    int i = 0;
    for (i - 0; i < pool->maxPoolSize; i++)
    {
        if (pool->ptrPool[i] == innerEvent)
            return i;
    }
    return -1;
}
/**
 * @brief
 *
 * @param innerEventHead
 * @param eventPoolSzie
 * @return int
 */
int InnerEventPoolDelete(struct InnerEventPool_S *pool)
{
    int iCount = 0;
    if (pool == NULL)
        return -1;
    for (iCount = 0; i < pool->maxPoolSize; i++)
    {
        if (innerEventHead[i] != 0)
            break;
    }
    if (innerEventHead != NULL && i >= pool->maxPoolSize)
    {
        Event_free(pool->ptrPool);
        Evnet_free(pool);
        innerEventHead = NULL;
        pool = NULL;
        return 0;
    }
    return -1;
}

STATIC_INLINE struct InnerEvent_S *InnerEventCheckNodeByString(struct InnerEventPool_S *pool, char *topicName, struct InnerFunctionNode_S *innerFunctionNode)
{
    int i = 0;
    struct InnerEvent_S *innerEvent = NULL;
    if (pool == NULL)
        return NULL;

    for (i = 0; i < pool->eventPoolSize; i++)
    {
        if (strcmp((pool->ptrPool[i])->strTopic, topicName) && ((innerFunctionNode == NULL) || ((innerFunctionNode != NULL) && (((pool->ptrPool[i])->innerFunctionNode->)callback == innerFunctionNode->callback))))
        {

            return (struct InnerEvent_S *)pool->ptrPool[i];
        }
    }
    return NULL;
}
STATIC_INLINE struct InnerEvent_S *InnerEventCheckNodeByNumber(struct InnerEventPool_S *pool, uint32_t topicNum, struct InnerFunctionNode_S *innerFunctionNode)
{
    int i = 0;
    if (pool == NULL)
        return NULL;
    for (i = 0; i < pool->eventPoolSize; i++)
    {
        if (((pool->ptrPool[i])->topicNum == topicNum) && ((innerFunctionNode == NULL) || ((innerFunctionNode != NULL) && (((pool->ptrPool[i])->innerFunctionNode->)callback == innerFunctionNode->callback))))
        {
            return (struct InnerEvent_S *)pool->ptrPool[i];
        }
    }
    return NULL;
}

static int InnerEventAddFunction(struct InnerEvent_S *innerEvent, struct InnerFunction_S *innerFunctionNode)
{
    if (innerFunctionNode == NULL)
        return -1;
    innerEvent->innerFunctionNode = Event_Malloc(struct InnerFunctionNode_S);
    if (innerEvent->innerFunction == NULL)
    {

        return -1;
    }
    innerEvent->innerFunctionNode->callback = innerFunctionNode->callback;
    innerEvent->innerFunctionNode->len = innerFunctionNode->len;
    if (innerEvent->innerFunctionNode->len > 0)
    {
        innerEvent->innerFunctionNode->param = Event_Malloc(sizeof(uint8_t) * (innerEvent->innerFunctionNode->len + 1));
        if (innerEvent->innerFunctionNode->param == -1)
        {
            Event_free(innerEvent->innerFunctionNode);
            innerEvent->innerFunctionNode = NULL;
            return -1;
        }
        memcpy(innerEvent->innerFunctionNode->param, innerFunctionNode->param, innerEvent->innerFunctionNode->len);
    }
    else
    {
        innerEvent->innerFunctionNode->len = 0;
        innerEvent->innerFunctionNode->param = NULL;
    }
    return 0;
}
// static InnerEventCreateTopic()
/**
 * @brief
 * @param  topicName
 * @return struct InnerEvent*
 * @author ken (kangjiening@openvalley.net)
 * @date 2023-06-08
 */
struct InnerEvent_S *InnerEventCreateString(struct InnerEventPool_S *pool, char *topicName, EventType evenType, struct InnerFunctionNode_S *innerFunctionNode)
{
    struct InnerEvent_S *innerEvent = NULL;
    int i = 0;
    if (topicName == NULL || pool == NULL)
        return NULL;
    MUTEX_Lock(pool->mutex);
    i = InnerEventGetIndex(pool);
    if (i < 0)
    {

        MUTEX_Unlock(pool->mutex);
        return NULL;
    }

    if ((innerEvent = InnerEventCheckNodeByString(pool, topicName, innerFuntionNode)) != NULL)
    {
        MUTEX_Unlock(pool->mutex);
        return innerEvent;
    }

    innerEvent = (struct InnerEvent_S *)Event_Malloc(sizeof(struct InnerEvent_S));
    if (innerEvent == NULL)
    {
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    innerEvent->topicName = (InnerTopic_S *)Event_Malloc(sizeof(InnerTopic_S));
    if (innerEvent->topicName == NULL)
    {
        Event_free(innerEvent);
        innerEvent = NULL;
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    memset((innerEvent->topicName).topic.strTopic, 0, sizeof((innerEvent->topicName).strTopic));
    uint8_t len = sizeof((innerEvent->topicName).topic.strTopic) > (strlen(topicName) + 1) ? (strlen(topicName) + 1) : sizeof((innerEvent->topicName).topic.strTopic);
    memcpy((innerEvent->topicName).topic.strTopic, topicName, len); // 这里后面考虑要用安全函数
    if (innerFunctionNode != NULL)
    {
        if (InnerEventAddFunction(innerEvent, innerFunctionNode) < 0)
        {
            Event_free(innerEvent->topicName);
            innerEvent->topicName = NULL;
            Event_free(innerEvent);
            innerEvent = NULL;
            MUTEX_Unlock(pool->mutex);
            return NULL;
        }
    }
    else
    {
        innerEvent->innerFunction = NULL;
    }
    innerEvent->eventType = eventType;
    innerEvent->innerTimer = NULL;

    pool->ptrPool[i] = innerEvent;
    MUTEX_Unlock(pool->mutex);
    return innerEvent;
}
/**
 * @brief
 * @param  topicNum
 * @return struct InnerEvent*
 * @author ken (kangjiening@openvalley.net)
 * @date 2023-06-08
 */
struct InnerEvent_S *InnerEventCreateNumber(struct InnerEventPool_S *pool, uint32_t numTopic, EventType evenType, InnerFunction_S *innerFunction)
{
    struct InnerEvent_S *innerEvent = NULL;
    int i = 0;
    if (pool == NULL)
        return NULL;
    MUTEX_Lock(pool->mutex);
    i = InnerEventGetIndex(pool);
    if (i < 0)
    {
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }

    if ((innerEvent = InnerEventCheckNodeByNumber(pool, topicNum, callback, param)) != NULL)
    {
        MUTEX_Unlock(pool->mutex);
        return innerEvent;
    }

    innerEvent = (struct InnerEvent_S *)Event_Malloc(sizeof(struct InnerEvent_S));
    if (innerEvent == NULL)
    {
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    innerEvent->topicName = (InnerTopic_S *)Event_Malloc(sizeof(InnerTopic_S));
    if (innerEvent->topicName == NULL)
    {
        Event_free(innerEvent);
        innerEvent = NULL;
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    innerEvent->topicName.topic.numTopic = numTopic;
    if (innerFunction != NULL)
    {
        if (InnerEventAddFunction(innerEvent, innerFunctionNode) < 0)
        {

            Event_free(innerEvent);
            innerEvent = NULL;
            MUTEX_Unlock(pool->mutex);
            return NULL;
        }
    }
    else
    {
        innerEvent->innerFunction = NULL;
    }
    innerEvent->eventType = eventType;
    innerEvent->innerTimer = NULL;
    pool->ptrPool[i] = innerEvent;
    MUTEX_Unlock(pool->mutex);
    return innerEvent;
}

/**
 * @brief
 * @param  callback
 * @param  param
 * @param  pri
 * @return struct InnerEvent*
 * @author ken (kangjiening@openvalley.net)
 * @date 2023-06-08
 */
struct InnerEvent_S *InnerEventCreateCallback(struct InnerEventPool_S *pool, EventType evenType, InnerFunction_S *innerFunction, InnerTimer_S *innerTimer)
{
    struct InnerEvent_S *innerEvent = NULL;
    if (pool == NULL)
        retrun NULL;
    if (innerFunction == NULL)
        return NULL;
    if (innerEventTimer == NULL)
        return NULL;
    MUTEX_Lock(pool->mutex);
    i = InnerEventGetIndex(pool);
    if (i < 0)
    {
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }

    innerEvent = (struct InnerEvent_S *)Event_Malloc(sizeof(InnerEvent_S));
    if (innerEvent == NULL)
    {
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    innerEvent->eventType = eventType;
    innerEvent->innerFunction = Event_Malloc(sizeof(InnerFunction_S));
    if (innerEvent->innerFunction == NULL)
    {
        Event_free(innerEvent);
        innerEvent = NULL;
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    if (InnerEventAddFunction(innerEvent, innerFunction) < 0)
    {
        Event_free(innerEvent->innerFunction);
        innerEvent->innerFunction = NULL;
        Event_free(innerEvent);
        innerEvent = NULL;
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    innerEvent->innerTimer = Event_Malloc(sizeof(InnerTimer_S));
    if (innerEvent->innerTimer)
    {
        Event_free(innerEvent->innerFunction);
        innerEvent->innerFunction = NULL;
        Event_free(innerEvent);
        innerEvent = NULL;
        MUTEX_Unlock(pool->mutex);
        return NULL;
    }
    (innerEvent->innerTimer)->timerOut = innerTimer->timerOut;
    (innerEvent->innerTimer)->count = innerTimer->count;
    (innerEvent->innerTimer)->pri = innerTimer->pri;

    innerEvent->topicName = NULL;

    pool->ptrPool[i] = innerEvent;
    MUTEX_Unlock(pool->mutex);
    return innerEvent;
}

/**
 * @brief
 * @param  innerEvent
 * @return int
 * @author ken (kangjiening@openvalley.net)
 * @date 2023-06-08
 */
int InnerEventDelete(struct InnerEventPool_S *pool, struct InnEvent *innerEvent)
{
    int i = 0;
    MUTEX_Lock(pool->mutex);
    if (innerEvent->topicName != NULL)
    {
        Event_free(innerEvent->topicName);
        innerEvent->topicName = NULL;
    }
    if (innerEvent->innerFunction != NULL)
    {
        if ((innerEvent->innerFunction)->param != NULL)
        {
            Event_free((innerEvent->innerFunction)->param);
            (innerEvent->innerFunction)->param = NULL;
        }
        (innerEvent->innerFunction)->callback = NULL;
        Event_free(innerEvent->innerFunction);
        innerEvent->innerFunction = NULL;
    }
    if (innerEvent->innerTimer != NULL)
    {
        Event_free(innerEvent->innerTimer);
        innerEvent->innerTimer = NULL;
    }
    if (innerEvent != NULL)
    {
        Event_free(innerEvent);
        innerEvent = NULL;
        i = InnerEventGetIndexByBody(pool, innerEvent);
        if (i >= 0)
            pool->ptrPool[i] = 0;
    }
    MUTEX_Unlock(pool->mutex);
    return 0;
}
